﻿using ApplicationBase.Core.Attributes;
using ApplicationBase.Core.Context;
using IdentityService.Application.QueryService;
using IdentityService.Infrastructure.Exceptions;
using MediatR;

namespace IdentityService.Application.Behaviours
{
    public class PermitCheckBehaviour<TRequest, TResponse> : IPipelineBehavior<TRequest, TResponse> where TRequest : IRequest<TResponse>
    {
        private readonly IPermitQueryService _permitQueryService;
        private readonly IServiceContext _serviceContext;
        public PermitCheckBehaviour(IPermitQueryService permitQueryService, IServiceContext serviceContext)
            => (_permitQueryService, _serviceContext) = (permitQueryService, serviceContext);

        public async Task<TResponse> Handle(TRequest request, RequestHandlerDelegate<TResponse> next, CancellationToken cancellationToken)
        {
            var checkPermitAttr = (CheckPermitAttribute) Attribute.GetCustomAttribute(typeof(TRequest), typeof(CheckPermitAttribute));
            if(checkPermitAttr != null) 
            {
                var set = await _permitQueryService.GetPermitRoleSet(checkPermitAttr.Name);
                var userRoles = _serviceContext.GetUserRoles();
                foreach(var role in userRoles)
                {
                    if (set.Roles.Contains(role))
                        return await next();
                }

                throw new NoPermitException();
            }

            return await next();
        }
    }
}
